from calendar import month
from decimal import Decimal

from app.controllers.customer.users import users_controller
from app.controllers.saas.performance_percentage import performance_percentage_controller
from app.core.ctx import CTX_USER_ID
from app.settings import settings
from dateutil.relativedelta import relativedelta
from dateutil.utils import today
from fastapi import APIRouter, Query, UploadFile
from tortoise.expressions import Q
from collections import defaultdict
from app.controllers.appointment.list import appointment_list_controller
from app.controllers.appointment.space import appointment_space_controller
from app.controllers.goods.goods import goods_controller
from app.controllers.orders.list import orders_list_controller
from app.core.dependency import DependCustomerAuth
from app.models import AppointmentDesigner, AppointmentList, OrdersList
from app.schemas.base import Success, SuccessExtra, Fail
from app.schemas.saas import *
from datetime import datetime, timedelta
from app.controllers.appointment.designer import appointment_designer_controller

mini_saas_appointment_router = APIRouter()
model_name = "预约"


@mini_saas_appointment_router.get("/3month", summary=f"查询3个月的每日预约合计")
async def do_settings_3month(
        month: str = Query("", description="月份"),
        space_id: int = Query(1, description="门店id"),
):
    if month == "":
        now_month = datetime.now().strftime("%Y-%m")
    else:
        now_month = month

    year = int(now_month.split("-")[0])  # 提取年份
    month = int(now_month.split("-")[1])  # 提取月份
    prev_month, current_month, next_month = await get_month_range(year, month)

    # 查询前一个月的预约数据
    prev_month_appointments = await AppointmentList.filter(
        time__gte=prev_month,
        time__lt=current_month,
        space_id=space_id
    ).values("time")

    # 查询当月的预约数据
    current_month_appointments = await AppointmentList.filter(
        time__gte=current_month,
        time__lt=next_month,
        space_id=space_id
    ).values("time")

    # 查询后一个月的预约数据
    next_month_appointments = await AppointmentList.filter(
        time__gte=next_month,
        time__lt=next_month + timedelta(days=31),
        space_id=space_id
    ).values("time")

    # 统计每天的预约数量
    def count_appointments(appointments):
        count_dict = defaultdict(int)
        for appointment in appointments:
            date = appointment["time"].strftime('%Y-%m-%d')  # 提取日期部分
            count_dict[date] += 1
        return [{"date": date, "nums": nums} for date, nums in count_dict.items()]

    # 合并结果
    result = []
    result.extend(count_appointments(prev_month_appointments))
    result.extend(count_appointments(current_month_appointments))
    result.extend(count_appointments(next_month_appointments))

    return SuccessExtra(data=result)


@mini_saas_appointment_router.get("/list", summary=f"查看某门店某天的预约记录")
async def do_settings_list(
        date: str = Query("", description="日期"),
        space_id: int = Query(1, description="门店id"),
):
    if date == "":
        date = datetime.now().strftime("%Y-%m-%d")

    space = await appointment_space_controller.do_detail(space_id)
    start = space['start']
    end = space['end']
    interval = space['interval']
    times_all = generate_time_slots(start=start, end=end, interval=interval)

    data_appointment = await AppointmentDesigner.filter(space_id__contains=[space_id]).values("id", "name")
    for item in data_appointment:
        item["ap_con"] = []
        designer_id = item["id"]
        q = Q(time__contains=date, designer_ids__contains=[designer_id], space_id=space_id, status=1)
        total, data_ap_designer = await appointment_list_controller.do_list(page=1, page_size=100, search=q,
                                                                            order_by="time")
        width = 80
        left_last = 0
        if data_ap_designer:
            for ap_item in data_ap_designer:
                ap_item['status_name'] = settings.APPOINTMENT_STATUS[ap_item['status']]
                if ap_item["longs"] > 0:
                    width = ap_item["longs"] / interval * 80
                left = calculate_intervals(start, ap_item["time"], interval)

                ap_item["width"] = width
                ap_item["left"] = left * 80 - left_last
                print(f"{ap_item['id']}计算间隔为：{ap_item["left"]},{left_last}")
                left_last = ap_item["left"] + width

            item["ap_con"] = data_ap_designer
    data = {
        "head": times_all,
        "list": data_appointment
    }
    return SuccessExtra(data=data)


@mini_saas_appointment_router.get("/schedule_appointments", summary=f"日程预约")
async def do_settings_list(
        date: str = Query("", description="日期"),
        space_id: int = Query(1, description="门店id"),
):
    if date == "":
        date = datetime.now().strftime("%Y-%m-%d")

    q = Q(time__contains=date, space_id=space_id, status=1)
    total, data = await appointment_list_controller.do_list(page=1, page_size=10000, search=q,
                                                            order_by="time")
    return SuccessExtra(data=data, total=total, page=1, page_size=10000)


@mini_saas_appointment_router.get("/appointment_list", summary=f"我的预约列表", dependencies=[DependCustomerAuth])
async def do_list(
        page: int = Query(1, description="页码"),
        page_size: int = Query(100, description="每页数量"),
        space_id: int = Query(None, description=" 门店id"),
        start_time: str = Query("", description="开始时间"),
        end_time: str = Query("", description="结束时间"),
):
    q = Q(status=1)
    if space_id:
        q &= Q(type=space_id)
    if start_time and end_time:
        q &= Q(time__range=[start_time, end_time])
    elif start_time:
        q &= Q(time__gte=start_time)
    elif end_time:
        q &= Q(time__lte=end_time)
    total, data = await appointment_list_controller.do_list(page=page, page_size=page_size, search=q)
    space_objs = await appointment_space_controller.level_list()

    for item in data:
        item['type_name'] = settings.APPOINTMENT_T[item['type']]
        if item['d_type'] > 0:
            item['d_type_name'] = settings.APPOINTMENT_TYPE[item['d_type']]
        else:
            item['d_type_name'] = "无"
        if item['space_id'] > 0:
            item['space_name'] = space_objs[item['space_id']]
        else:
            item['space_name'] = "无"
        item['status_name'] = settings.APPOINTMENT_STATUS[item['status']]
        if item['designer_names']:
            item['designer_name_s'] = ", ".join(item['designer_names'])
        else:
            item['designer_name_s'] = ""
        if item['ex_project_names']:
            item['ex_names'] = ", ".join(item['ex_project_names'])
            item['project_name_s'] = f"{item['project_name']}({item['ex_names']})"
        else:
            item['ex_names'] = ""
    return SuccessExtra(data=data, total=total, page=page, page_size=page_size)


@mini_saas_appointment_router.get("/today_info", summary=f"查看{model_name}今日数据")
async def do_today_info(
        space_id: int = Query(1, description="门店id")
):
    now = datetime.now()
    # 今天的开始时间（00:00:00）
    start_of_today = now.replace(hour=0, minute=0, second=0, microsecond=0)
    # 明天的开始时间（00:00:00）
    start_of_tomorrow = start_of_today + timedelta(days=1)

    pay_order_count, pay_order_price_count = await orders_list_controller.do_total(space_id)
    pay_order_price_count = 0 if pay_order_price_count is None else pay_order_price_count
    # 下单 预约 成交 到店

    appointment_count = await AppointmentList.filter(space_id=space_id, status=1, time__gte=start_of_today,
                                                     time__lt=start_of_tomorrow).count()

    appointment_arrive = await appointment_list_controller.do_total(space_id)

    data = {
        "pay_order_count": pay_order_count,
        "pay_order_price_count": pay_order_price_count,
        "appointment_count": appointment_count,
        "appointment_arrive": appointment_arrive,
    }

    return Success(data=data)


@mini_saas_appointment_router.get("/get_yeji", summary=f"当前业绩", dependencies=[DependCustomerAuth])
async def get_yeji_list(
        page: int = Query(1, description="页码"),
        page_size: int = Query(10, description="每页数量"),
        space_id: int = Query(1, description="门店id"),
        type: int = Query(1, description="类型"),
):
    user_id = CTX_USER_ID.get()
    user_data = await users_controller.get(user_id)
    user_id = user_data.user_id
    q = Q(space_id=space_id, status=1, user_id=user_id)
    now = datetime.now()

    if type == 1:
        # 今天的开始时间（00:00:00）
        start_of_today = now.replace(hour=0, minute=0, second=0, microsecond=0)
        # 明天的开始时间（00:00:00）
        start_of_tomorrow = start_of_today + timedelta(days=1)
        q &= Q(created_at__range=[start_of_today, start_of_tomorrow])
    if type == 2:
        # 本月第一天 00:00:00
        first_day_of_month = datetime(now.year, now.month, 1)
        # 下个月第一天 00:00:00
        first_day_of_next_month = (first_day_of_month + relativedelta(months=1))
        q &= Q(created_at__range=[first_day_of_month, first_day_of_next_month])
    total, data = await performance_percentage_controller.do_yeji(page=page, page_size=page_size, search=q)

    return SuccessExtra(data=data, total=total, page=page, page_size=page_size)


@mini_saas_appointment_router.get("/get_total_yeji", summary=f"总业绩", dependencies=[DependCustomerAuth])
async def get_total_yeji(
        space_id: int = Query(1, description="门店id"),
):
    user_id = CTX_USER_ID.get()
    user_data = await users_controller.get(user_id)
    user_id = user_data.user_id

    now = datetime.now()

    q = Q(space_id=space_id, status=1, user_id=user_id)
    total_count, total_data = await performance_percentage_controller.do_total_yeji(search=q)

    # 今天的开始时间（00:00:00）
    start_of_today = now.replace(hour=0, minute=0, second=0, microsecond=0)
    # 明天的开始时间（00:00:00）
    start_of_tomorrow = start_of_today + timedelta(days=1)
    q = Q(created_at__range=[start_of_today, start_of_tomorrow], space_id=space_id, status=1)
    today_count, today_data = await performance_percentage_controller.do_total_yeji(search=q)

    # 本月第一天 00:00:00
    first_day_of_month = datetime(now.year, now.month, 1)
    # 下个月第一天 00:00:00
    first_day_of_next_month = (first_day_of_month + relativedelta(months=1))
    q1 = Q(created_at__range=[first_day_of_month, first_day_of_next_month], space_id=space_id, status=1,
           user_id=user_id)
    month_count, month_data = await performance_percentage_controller.do_total_yeji(search=q1)

    total_data = sanitize_data(convert_decimals(total_data))
    month_data = sanitize_data(convert_decimals(month_data))
    today_data = sanitize_data(convert_decimals(today_data))

    data = {
        "total_data": total_data['total'],
        "month_data": month_data['total'],
        "today_data": today_data['total'],
        "total_count": total_count,
    }

    return Success(data=data)


def sanitize_data(data):
    if data is None:
        return 0
    elif isinstance(data, dict):
        return {k: sanitize_data(v) for k, v in data.items()}
    elif isinstance(data, (list, tuple)):
        return [sanitize_data(x) for x in data]
    return data


def convert_decimals(obj):
    if isinstance(obj, Decimal):
        return float(obj)
    elif isinstance(obj, dict):
        return {k: convert_decimals(v) for k, v in obj.items()}
    elif isinstance(obj, (list, tuple)):
        return [convert_decimals(x) for x in obj]
    return obj


def format_time(time):
    if isinstance(time, datetime):  # 如果是 datetime 对象
        return time.strftime("%Y-%m-%d %H:%M:%S")
    elif isinstance(time, str) and time:  # 如果是非空字符串
        dt = datetime.fromisoformat(time)
        return dt.strftime("%Y-%m-%d %H:%M:%S")
    return None  # 其他情况返回 None


async def get_month_range(year, month):
    """获取指定年月的第一天和最后一天"""
    if month == 1:
        prev_month = datetime(year - 1, 12, 1)
    else:
        prev_month = datetime(year, month - 1, 1)

    if month == 12:
        next_month = datetime(year + 1, 1, 1)
    else:
        next_month = datetime(year, month + 1, 1)

    current_month = datetime(year, month, 1)
    return prev_month, current_month, next_month


def generate_time_slots(start, end, interval):
    # 将开始时间和结束时间转换为 datetime 对象
    start_time = datetime.strptime(start, '%H:%M')
    end_time = datetime.strptime(end, '%H:%M')

    # 初始化时间列表
    time_slots = []

    # 循环生成时间点
    current_time = start_time
    while current_time <= end_time:
        # 将时间点添加到列表
        time_slots.append(current_time.strftime('%H:%M'))
        # 增加时间间隔
        current_time += timedelta(minutes=interval)

    return time_slots


def calculate_intervals(start, target_time_str, interval):
    # 1. 将 target_time_str 转换为 datetime 对象
    target_time = datetime.strptime(target_time_str, "%Y-%m-%d %H:%M:%S")

    # 2. 将 start 转换为 datetime 对象，并将日期部分设置为 target_time 的日期
    start_time = datetime.strptime(start, "%H:%M").replace(
        year=target_time.year,
        month=target_time.month,
        day=target_time.day
    )

    # 3. 如果 start_time 晚于 target_time，说明 start_time 是前一天的
    if start_time > target_time:
        start_time -= timedelta(days=1)

    # 4. 计算时间差
    time_diff = target_time - start_time

    # 4. 将时间差转换为分钟
    total_minutes = time_diff.total_seconds() / 60

    # 5. 计算间隔数
    interval_count = int(total_minutes // interval)

    return interval_count
